import { _decorator, Component, Node, AudioClip, AudioSource, resources, game, director, Director } from 'cc';
const { ccclass, property } = _decorator;

/**
 * 音频管理器
 * 负责全局音频控制
 */
@ccclass('AudioManager')
export class AudioManager extends Component {
    private static _instance: AudioManager = null;
    
    public static get instance(): AudioManager {
        return this._instance;
    }
    
    @property(AudioSource)
    private musicSource: AudioSource = null;
    
    @property(AudioSource)
    private soundSource: AudioSource = null;
    
    private _musicEnabled: boolean = true;
    private _soundEnabled: boolean = true;
    
    private _audioClips: Map<string, AudioClip> = new Map();
    
    // 生命周期方法
    onLoad() {
        // 单例模式，不设为常驻节点
        if (AudioManager._instance === null) {
            AudioManager._instance = this;
            console.log("AudioManager 已初始化");
        } else {
            console.log("已存在 AudioManager 实例，销毁当前节点");
            this.node.destroy();
            return;
        }
        
        // 确保有音频源组件
        if (!this.musicSource) {
            this.musicSource = this.getComponent(AudioSource) || this.addComponent(AudioSource);
            this.musicSource.loop = true;
            this.musicSource.volume = 0.5;
        }
        
        if (!this.soundSource) {
            // 为音效创建单独的AudioSource
            const soundNode = new Node('SoundSource');
            this.node.addChild(soundNode);
            this.soundSource = soundNode.addComponent(AudioSource);
            this.soundSource.volume = 1.0;
        }
        
        // 预加载常用音频资源
        this.preloadCommonAudio();
    }
    
    onDestroy() {
        // 当节点被销毁时清除单例引用
        if (AudioManager._instance === this) {
            console.log("AudioManager 实例被销毁");
            AudioManager._instance = null;
        }
        
        // 移除场景切换事件监听
        director.off(Director.EVENT_AFTER_SCENE_LAUNCH, this.onSceneChanged, this);
    }
    
    /**
     * 场景切换时处理
     */
    private onSceneChanged() {
        console.log("场景已切换，确保AudioManager正常工作");
        
        // 如果当前实例已经被销毁但静态引用还在，修复它
        if (!this.isValid && AudioManager._instance === this) {
            AudioManager._instance = null;
            console.error("AudioManager实例已失效，已重置静态引用");
            return;
        }
        
        // 确保音频设置仍然有效
        if (this._musicEnabled && this.musicSource && this.musicSource.clip && !this.musicSource.playing) {
            console.log("重新开始播放背景音乐");
            this.musicSource.play();
        }
    }
    
    /**
     * 预加载常用音频资源
     */
    private preloadCommonAudio(): void {
        const soundList = [
            'button_click_ok',   // 按钮点击/确认音效
            'button_click_no',   // 操作失败/取消音效
            'tile_match',        // 方块消除音效
            'combo',             // 连击音效
            'game_start',        // 游戏开始音效
            'game_over'          // 游戏结束音效
        ];
        
        soundList.forEach(name => {
            this.loadAudioClip(`audio/${name}`);
        });
        
        // 预加载背景音乐
        this.loadAudioClip('audio/bgm_game', (clip) => {
            // 游戏开始时自动播放背景音乐
            if (this._musicEnabled) {
                this.musicSource.clip = clip;
                this.musicSource.play();
            }
        });
    }
    
    /**
     * 加载音频剪辑
     */
    private loadAudioClip(path: string, callback?: (clip: AudioClip) => void): void {
        resources.load<AudioClip>(path, AudioClip, (err, clip) => {
            if (err) {
                console.error(`加载音频失败: ${path}`, err);
                return;
            }
            
            // 缓存音频剪辑
            const key = path.split('/').pop();
            this._audioClips.set(key, clip);
            
            if (callback) {
                callback(clip);
            }
        });
    }
    
    /**
     * 获取音频剪辑
     */
    private getAudioClip(name: string): AudioClip {
        // 从缓存获取
        if (this._audioClips.has(name)) {
            return this._audioClips.get(name);
        }
        
        // 如果没有找到，尝试加载
        this.loadAudioClip(`audio/${name}`);
        return null;
    }
    
    /**
     * 播放背景音乐
     */
    public playMusic(name: string, fade: boolean = false): void {
        if (!this._musicEnabled) return;
        
        const clip = this.getAudioClip(name);
        if (!clip) {
            // 如果没有立即找到音频，尝试加载并播放
            this.loadAudioClip(`audio/${name}`, (loadedClip) => {
                if (this._musicEnabled) {
                    this.musicSource.clip = loadedClip;
                    this.musicSource.play();
                }
            });
            return;
        }
        
        // 播放音乐
        this.musicSource.clip = clip;
        this.musicSource.play();
    }
    
    /**
     * 停止背景音乐
     */
    public stopMusic(): void {
        this.musicSource.stop();
    }
    
    /**
     * 播放音效
     */
    public playSound(name: string): void {
        if (!this._soundEnabled) return;
        
        const clip = this.getAudioClip(name);
        if (!clip) {
            // 如果没有立即找到音频，尝试加载并播放
            this.loadAudioClip(`audio/${name}`, (loadedClip) => {
                if (this._soundEnabled) {
                    this.soundSource.playOneShot(loadedClip);
                }
            });
            return;
        }
        
        // 播放音效
        this.soundSource.playOneShot(clip);
    }
    
    /**
     * 设置音乐是否开启
     */
    public setMusicEnabled(enabled: boolean): void {
        this._musicEnabled = enabled;
        
        if (this.musicSource) {
            if (enabled) {
                if (this.musicSource.clip && !this.musicSource.playing) {
                    this.musicSource.play();
                }
            } else {
                this.musicSource.pause();
            }
        }
    }
    
    /**
     * 获取音乐是否开启
     */
    public isMusicEnabled(): boolean {
        return this._musicEnabled;
    }
    
    /**
     * 设置音效是否开启
     */
    public setSoundEnabled(enabled: boolean): void {
        this._soundEnabled = enabled;
    }
    
    /**
     * 获取音效是否开启
     */
    public isSoundEnabled(): boolean {
        return this._soundEnabled;
    }
} 